package cn.lenchu.stock.xueqiu;

import cn.lenchu.stock.model.StandardCodeTypeEnum;
import static cn.lenchu.stock.model.StandardCodeTypeEnum.SUFFIX_SEPARATOR;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * @author lenchu
 */
public class XueQiuCode {

    private final String symbol;

    @Getter
    private final String code;
    private final String exchange;

    @Getter
    private final StandardCodeTypeEnum codeType;
    @Getter
    private final String standardCode;

    private static final String XQ_EX_JJ = "F";
    private static final String XQ_EX_SH = "SH";
    private static final String XQ_EX_SZ = "SZ";
    private static final String XQ_EX_HK = "";

    private static final String XQ_EX_CSI = "CSI";
    private static final String XQ_EX_HKI = "HK";

    public static XueQiuCode fromStandardCode(String standardCode) {
        if (StringUtils.contains(standardCode, SUFFIX_SEPARATOR)) {
            String code = StringUtils.substringBeforeLast(standardCode, SUFFIX_SEPARATOR);
            String suffix = StringUtils.substringAfterLast(standardCode, SUFFIX_SEPARATOR);
            StandardCodeTypeEnum codeTypeEnum = StandardCodeTypeEnum.getBySuffix(suffix);
            if (codeTypeEnum == null || StringUtils.isBlank(code)) {
                return null;
            }
            return new XueQiuCode(code, codeTypeEnum);
        }
        return null;
    }

    public static XueQiuCode fromXqCodeAndType(String xqCode, Integer type) {
        if (StringUtils.isBlank(xqCode) || type == null) {
            return null;
        }
        StandardCodeTypeEnum codeType = null;
        String code = null;
        if (Types.HS.contains(type)) {
            String standardSuffix = StringUtils.substring(xqCode, 0, 2);
            code = StringUtils.substringAfter(xqCode, standardSuffix);
            codeType = StandardCodeTypeEnum.getBySuffix(standardSuffix);
        } else if (Types.HK.contains(type)) {
            code = xqCode;
            codeType = StandardCodeTypeEnum.HK;
        } else if (Types.JJ.contains(type)) {
            codeType = StandardCodeTypeEnum.JJ;
            code = StringUtils.substringAfter(xqCode, "F");
        } else if (Types.CSI.contains(type)) {
            codeType = StandardCodeTypeEnum.CSI;
            code = StringUtils.substringAfter(xqCode, "CSI");
        } else if (Types.HKI.contains(type)) {
            codeType = StandardCodeTypeEnum.HKI;
            code = StringUtils.substringAfter(xqCode, "HK");
        }
        if (codeType == null || StringUtils.isBlank(code)) {
            return null;
        } else {
            return new XueQiuCode(code, codeType);
        }
    }

    private interface Types {
        // 沪深市场     14: 可转债
        Set<Integer> HS = new HashSet<>(Arrays.asList(11, 12, 13, 14));

        // 港股市场
        Set<Integer> HK = new HashSet<>(Collections.singletonList(30));

        // 基金
        Set<Integer> JJ = new HashSet<>(Collections.singletonList(23));

        // 中证指数
        Set<Integer> CSI = new HashSet<>(Collections.singletonList(26));

        // 港股指数
        Set<Integer> HKI = new HashSet<>(Collections.singletonList(31));
    }

    private XueQiuCode(String code, StandardCodeTypeEnum codeType) {
        this.code = code;
        this.codeType = codeType;
        this.standardCode = codeType.getStandardCode(code);
        switch (codeType) {
            case JJ:
                this.exchange = XQ_EX_JJ;
                break;
            case HK:
                this.exchange = XQ_EX_HK;
                break;
            case SZ:
                this.exchange = XQ_EX_SZ;
                break;
            case SH:
                this.exchange = XQ_EX_SH;
                break;
            case CSI:
                this.exchange = XQ_EX_CSI;
                break;
            case HKI:
                this.exchange = XQ_EX_HKI;
                break;
            default:
                throw new RuntimeException("what's the code type? " + codeType.toString());
        }
        this.symbol = this.exchange + this.code;
    }

    public boolean isJj() {
        return StringUtils.equals(XQ_EX_JJ, this.exchange);
    }

    public String getXqCode() {
        return symbol;
    }
}
